package io.huaguoguo.nio;

import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.Charset;
import java.util.Iterator;

/**
 * 描述：  <br>
 * CreateDate: 2021/6/1 <br>
 *
 * @author huaguoguo
 */
@Slf4j
public class NIOServer {

    public final static int PORT = 8888;
    private Selector selector;
    private HttpDecoder httpDecoder = new HttpDecoder();

    public void init() throws IOException {
        // 创建一个选择器
        this.selector = Selector.open();
        ServerSocketChannel channel = ServerSocketChannel.open();
        // 服务通道非阻塞
        channel.configureBlocking(false);
        ServerSocket serverSocket = channel.socket();
        serverSocket.bind(new InetSocketAddress(PORT));
        log.info("nio socket启动，端口：" + PORT);
        // 注册OP_ACCEPT事件
        channel.register(selector, SelectionKey.OP_ACCEPT);
        // 监听
        while (true) {
            int count = selector.select();
            if (count <= 0) {
                continue;
            }
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                try {
                    SelectionKey key = iterator.next();
                    if (key.isAcceptable()) {
                        log.info("有新连接");
                        final SocketChannel clientChannel = channel.accept();
                        clientChannel.configureBlocking(false);
                        //将socketChannel注册到selector，关注事件为 OP_READ，同时给SocketChannel关联一个Buffer
                        clientChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
                    }
                    if (key.isReadable()) {
                        log.info("读就绪");
                        SocketChannel clientChannel = (SocketChannel) key.channel();
                        ByteBuffer buffer = (ByteBuffer) key.attachment();
                        clientChannel.read(buffer);
                        HttpServletRequest request = httpDecoder.decode(buffer);
                        // 返回消息
                        clientChannel.write(ByteBuffer.wrap("哈哈哈".getBytes("UTF-8")));
                    }
                } catch (Exception e) {
                    log.error(e.getMessage(), e);
                } finally {
                    // 防止重复操作
                    iterator.remove();
                }


            }
        }
    }


    public static void main(String[] args) throws IOException {
        NIOServer nioServer = new NIOServer();
        nioServer.init();
    }
}
